home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / net_mp.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  11KB  |  444 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // net_mpath.c
  21.  
  22. #include <dpmi.h>
  23. #include "quakedef.h"
  24. #include "mpdosock.h"
  25.  
  26. short flat_selector;
  27.  
  28. int WSAGetLastError(void);
  29. void sockets_flush(void);
  30.  
  31. extern cvar_t hostname;
  32.  
  33. #define MAXHOSTNAMELEN        256
  34.  
  35. static int net_acceptsocket = -1;        // socket for fielding new connections
  36. static int net_controlsocket;
  37. static int net_broadcastsocket = 0;
  38. //static qboolean ifbcastinit = false;
  39. static struct qsockaddr broadcastaddr;
  40.  
  41. static unsigned long myAddr;
  42.  
  43. #include "net_mp.h"
  44.  
  45.  
  46. //=============================================================================
  47.  
  48. int MPATH_Init (void)
  49. {
  50.     int        i;
  51.     struct hostent *local = NULL;
  52.     char    buff[MAXHOSTNAMELEN];
  53.     struct qsockaddr addr;
  54.     char    *p;
  55.  
  56.     if (COM_CheckParm ("-mpath") == 0)
  57.         return -1;
  58.  
  59.    flat_selector = __dpmi_allocate_ldt_descriptors(1);
  60.    if (flat_selector == -1) {
  61.       Con_Printf("MPATH_Init: Can't get flat selector\n");
  62.       return -1;
  63.    }
  64.    if (__dpmi_set_segment_base_address(flat_selector, 0) == -1) {
  65.       Con_Printf("MPATH_Init: Can't seg flat base!\n");
  66.       return -1;
  67.    }
  68.    if (__dpmi_set_segment_limit(flat_selector, 0xffffffff) == -1) {
  69.       Con_Printf("MPATH_Init: Can't set segment limit\n");
  70.       return -1;
  71.    }
  72.     // determine my name & address
  73.     if (gethostname(buff, MAXHOSTNAMELEN) == 0)
  74.         local = gethostbyname(buff);
  75.     if (local)
  76.     {
  77.         myAddr = *(int *)local->h_addr_list[0];
  78.  
  79.         // if the quake hostname isn't set, set it to the machine name
  80.         if (Q_strcmp(hostname.string, "UNNAMED") == 0)
  81.         {
  82.             // see if it's a text IP address (well, close enough)
  83.             for (p = buff; *p; p++)
  84.                 if ((*p < '0' || *p > '9') && *p != '.')
  85.                     break;
  86.  
  87.             // if it is a real name, strip off the domain; we only want the host
  88.             if (*p)
  89.             {
  90.                 for (i = 0; i < 15; i++)
  91.                     if (buff[i] == '.')
  92.                         break;
  93.                 buff[i] = 0;
  94.             }
  95.             Cvar_Set ("hostname", buff);
  96.         }
  97.     }
  98.  
  99.     if ((net_controlsocket = MPATH_OpenSocket (0)) == -1)
  100.         Sys_Error("MPATH_Init: Unable to open control socket\n");
  101.  
  102.     ((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
  103.     ((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
  104.     ((struct sockaddr_in *)&broadcastaddr)->sin_port = htons(net_hostport);
  105.  
  106.     MPATH_GetSocketAddr (net_controlsocket, &addr);
  107.     Q_strcpy(my_tcpip_address,  MPATH_AddrToString (&addr));
  108.     p = Q_strrchr (my_tcpip_address, ':');
  109.     if (p)
  110.         *p = 0;
  111.  
  112.     Con_Printf("MPath Initialized\n");
  113.     tcpipAvailable = true;
  114.  
  115.     return net_controlsocket;
  116. }
  117.  
  118. //=============================================================================
  119.  
  120. void MPATH_Shutdown (void)
  121. {
  122.     MPATH_Listen (false);
  123.     MPATH_CloseSocket (net_controlsocket);
  124. }
  125.  
  126. //=============================================================================
  127.  
  128. void MPATH_Listen (qboolean state)
  129. {
  130.     // enable listening
  131.     if (state)
  132.     {
  133.         if (net_acceptsocket != -1)
  134.             return;
  135.         if ((net_acceptsocket = MPATH_OpenSocket (net_hostport)) == -1)
  136.             Sys_Error ("MPATH_Listen: Unable to open accept socket\n");
  137.         return;
  138.     }
  139.  
  140.     // disable listening
  141.     if (net_acceptsocket == -1)
  142.         return;
  143.     MPATH_CloseSocket (net_acceptsocket);
  144.     net_acceptsocket = -1;
  145. }
  146.  
  147. //=============================================================================
  148.  
  149. int MPATH_OpenSocket (int port)
  150. {
  151.     int newsocket;
  152.     struct sockaddr_in address;
  153.     u_long _true = 1;
  154.  
  155.     if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  156.         return -1;
  157.  
  158.     if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
  159.         goto ErrorReturn;
  160.  
  161.     address.sin_family = AF_INET;
  162.     address.sin_addr.s_addr = INADDR_ANY;
  163.     address.sin_port = htons(port);
  164.     if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
  165.         goto ErrorReturn;
  166.  
  167.     return newsocket;
  168.  
  169. ErrorReturn:
  170.     closesocket (newsocket);
  171.     return -1;
  172. }
  173.  
  174. //=============================================================================
  175.  
  176. int MPATH_CloseSocket (int socket)
  177. {
  178.     if (socket == net_broadcastsocket)
  179.         net_broadcastsocket = 0;
  180.     return closesocket (socket);
  181. }
  182.  
  183.  
  184. //=============================================================================
  185. /*
  186. ============
  187. PartialIPAddress
  188.  
  189. this lets you type only as much of the net address as required, using
  190. the local network components to fill in the rest
  191. ============
  192. */
  193. static int PartialIPAddress (char *in, struct qsockaddr *hostaddr)
  194. {
  195.     char buff[256];
  196.     char *b;
  197.     int addr;
  198.     int num;
  199.     int mask;
  200.     int run;
  201.     int port;
  202.     
  203.     buff[0] = '.';
  204.     b = buff;
  205.     strcpy(buff+1, in);
  206.     if (buff[1] == '.')
  207.         b++;
  208.  
  209.     addr = 0;
  210.     mask=-1;
  211.     while (*b == '.')
  212.     {
  213.         b++;
  214.         num = 0;
  215.         run = 0;
  216.         while (!( *b < '0' || *b > '9'))
  217.         {
  218.           num = num*10 + *b++ - '0';
  219.           if (++run > 3)
  220.               return -1;
  221.         }
  222.         if ((*b < '0' || *b > '9') && *b != '.' && *b != ':' && *b != 0)
  223.             return -1;
  224.         if (num < 0 || num > 255)
  225.             return -1;
  226.         mask<<=8;
  227.         addr = (addr<<8) + num;
  228.     }
  229.     
  230.     if (*b++ == ':')
  231.         port = Q_atoi(b);
  232.     else
  233.         port = net_hostport;
  234.  
  235.     hostaddr->sa_family = AF_INET;
  236.     ((struct sockaddr_in *)hostaddr)->sin_port = htons((short)port);    
  237.     ((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
  238.     
  239.     return 0;
  240. }
  241. //=============================================================================
  242.  
  243. int MPATH_Connect (int socket, struct qsockaddr *addr)
  244. {
  245.     return 0;
  246. }
  247.  
  248. //=============================================================================
  249.  
  250. int MPATH_CheckNewConnections (void)
  251. {
  252.     char buf[4];
  253.  
  254.     if (net_acceptsocket == -1)
  255.         return -1;
  256.  
  257.     if (recvfrom (net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0)
  258.         return net_acceptsocket;
  259.     return -1;
  260. }
  261.  
  262. //=============================================================================
  263.  
  264. int MPATH_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
  265. {
  266.     int addrlen = sizeof (struct qsockaddr);
  267.     int ret;
  268.  
  269.     ret = recvfrom (socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
  270.     if (ret == -1)
  271.     {
  272.         int errno = WSAGetLastError();
  273.  
  274.         if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
  275.             return 0;
  276.  
  277.     }
  278.     return ret;
  279. }
  280.  
  281. //=============================================================================
  282.  
  283. int MPATH_MakeSocketBroadcastCapable (int socket)
  284. {
  285.     int    i = 1;
  286.  
  287.     // make this socket broadcast capable
  288.     if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
  289.         return -1;
  290.     net_broadcastsocket = socket;
  291.  
  292.     return 0;
  293. }
  294.  
  295. //=============================================================================
  296.  
  297. int MPATH_Broadcast (int socket, byte *buf, int len)
  298. {
  299.     int ret;
  300.  
  301.     if (socket != net_broadcastsocket)
  302.     {
  303.         if (net_broadcastsocket != 0)
  304.             Sys_Error("Attempted to use multiple broadcasts sockets\n");
  305.         ret = MPATH_MakeSocketBroadcastCapable (socket);
  306.         if (ret == -1)
  307.         {
  308.             Con_Printf("Unable to make socket broadcast capable\n");
  309.             return ret;
  310.         }
  311.     }
  312.  
  313.     return MPATH_Write (socket, buf, len, &broadcastaddr);
  314. }
  315.  
  316. //=============================================================================
  317.  
  318. int MPATH_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
  319. {
  320.     int ret;
  321.  
  322.     ret = sendto (socket, buf, len, 0, (struct sockaddr *)addr, sizeof(struct qsockaddr));
  323.     if (ret == -1)
  324.         if (WSAGetLastError() == WSAEWOULDBLOCK)
  325.             return 0;
  326.  
  327.     sockets_flush();
  328.  
  329.     return ret;
  330. }
  331.  
  332. //=============================================================================
  333.  
  334. char *MPATH_AddrToString (struct qsockaddr *addr)
  335. {
  336.     static char buffer[22];
  337.     int haddr;
  338.  
  339.     haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
  340.     sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
  341.     return buffer;
  342. }
  343.  
  344. //=============================================================================
  345.  
  346. int MPATH_StringToAddr (char *string, struct qsockaddr *addr)
  347. {
  348.     int ha1, ha2, ha3, ha4, hp;
  349.     int ipaddr;
  350.  
  351.     sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
  352.     ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
  353.  
  354.     addr->sa_family = AF_INET;
  355.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
  356.     ((struct sockaddr_in *)addr)->sin_port = htons(hp);
  357.     return 0;
  358. }
  359.  
  360. //=============================================================================
  361.  
  362. int MPATH_GetSocketAddr (int socket, struct qsockaddr *addr)
  363. {
  364.     int addrlen = sizeof(struct qsockaddr);
  365.     unsigned int a;
  366.  
  367.     Q_memset(addr, 0, sizeof(struct qsockaddr));
  368.     getsockname(socket, (struct sockaddr *)addr, &addrlen);
  369.     a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  370.     if (a == 0 || a == inet_addr("127.0.0.1"))
  371.         ((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
  372.  
  373.     return 0;
  374. }
  375.  
  376. //=============================================================================
  377.  
  378. int MPATH_GetNameFromAddr (struct qsockaddr *addr, char *name)
  379. {
  380.     struct hostent *hostentry;
  381.  
  382.     hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
  383.     if (hostentry)
  384.     {
  385.         Q_strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
  386.         return 0;
  387.     }
  388.  
  389.     Q_strcpy (name, MPATH_AddrToString (addr));
  390.     return 0;
  391. }
  392.  
  393. //=============================================================================
  394.  
  395. int MPATH_GetAddrFromName(char *name, struct qsockaddr *addr)
  396. {
  397.     struct hostent *hostentry;
  398.  
  399.     if (name[0] >= '0' && name[0] <= '9')
  400.         return PartialIPAddress (name, addr);
  401.     
  402.     hostentry = gethostbyname (name);
  403.     if (!hostentry)
  404.         return -1;
  405.  
  406.     addr->sa_family = AF_INET;
  407.     ((struct sockaddr_in *)addr)->sin_port = htons(net_hostport);    
  408.     ((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
  409.  
  410.     return 0;
  411. }
  412.  
  413. //=============================================================================
  414.  
  415. int MPATH_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
  416. {
  417.     if (addr1->sa_family != addr2->sa_family)
  418.         return -1;
  419.  
  420.     if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
  421.         return -1;
  422.  
  423.     if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
  424.         return 1;
  425.  
  426.     return 0;
  427. }
  428.  
  429. //=============================================================================
  430.  
  431. int MPATH_GetSocketPort (struct qsockaddr *addr)
  432. {
  433.     return ntohs(((struct sockaddr_in *)addr)->sin_port);
  434. }
  435.  
  436.  
  437. int MPATH_SetSocketPort (struct qsockaddr *addr, int port)
  438. {
  439.     ((struct sockaddr_in *)addr)->sin_port = htons(port);
  440.     return 0;
  441. }
  442.  
  443. //=============================================================================
  444.